<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2021/2/7
 * Time: 23:52
 */
declare(strict_types=1);

namespace App\Service;
use App\Model\Dao\MchAccountAccessDao;
use App\Model\Dao\MchAccountAccessDetailDao;
use App\Model\Dao\MchAccountDao;
use App\Model\Dao\MchInfoDao;
use App\Model\Dao\RateCommissionSalesDao;
use App\Model\Dao\RateCostDao;
use App\Model\Dao\RateSettleDao;
use App\Model\Dao\SysAdminDao;
use App\Model\Dao\TradeOrderDetailDao;
use App\Model\Dao\TradeOrderForceSuccessSingleDao;
use App\Utils\CustomUtils;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Exception;

/**
 * Class SettleTradeOrderService
 * @package App\Service
 * 交易订单结算
 */
class SettleTradeOrderService extends CommonService
{

    /**
     * @Inject()
     * @var TradeOrderDetailDao
     */
    private $TradeOrderDetailDao;

    /**
     * @Inject()
     * @var MchInfoDao
     */
    private $MchInfoDao;

    /**
     * @Inject()
     * @var SysAdminDao
     */
    private $SysAdminDao;

    /**
     * @Inject()
     * @var RateCommissionSalesDao
     */
    private $RateCommissionSalesDao;

    /**
     * @Inject()
     * @var RateCostDao
     */
    private $RateCostDao;

    /**
     * @Inject()
     * @var MchAccountDao
     */
    private $MchAccountDao;

    /**
     * @Inject()
     * @var MchAccountAccessDao
     */
    private $MchAccountAccessDao;

    /**
     * @Inject()
     * @var MchAccountAccessDetailDao
     */
    private $MchAccountAccessDetailDao;

    /**
     * @Inject()
     * @var RateSettleDao
     */
    private $RateSettleDao;

    /**
     * @Inject()
     * @var TradeOrderForceSuccessSingleDao
     */
    private $TradeOrderForceSuccessSingleDao;

    /**
     * @Inject()
     * @var CountAmountService
     */
    private $CountAmountService;

    public function handle($param) {

        // 校验
        $tradeOrder = $this->TradeOrderDetailDao->get($param['orderId']);
        if(!$tradeOrder) {
            throw new Exception('订单不存在，终止处理', FAILED_CODE);
        }
        if($tradeOrder['isSettle'] == 2) {
            throw new Exception('订单已经结算', FAILED_CODE);
        }
        if($tradeOrder['transStatus'] != 6) {
            throw new Exception('订单还没收到银行的支付成功回调，不能被结算', FAILED_CODE);
        }
        $isAccess = $this->MchAccountAccessDao->getWhere(['orderId' => $param['orderId'], 'accessType' => ACCESS_TYPE_TRADE_ORDER]);
        if ($isAccess) {
            throw new Exception('订单已经入账', FAILED_CODE);
        }
        $mchAccount = $this->MchAccountDao->get($param['mchAccountId']);
        if(!$mchAccount) {
            throw new Exception('查询账户记录失败', FAILED_CODE);
        }
        $rateSettle = $this->RateSettleDao->getByMchId($tradeOrder['mchId']);
        if(!$rateSettle) {
            throw new Exception('查询商户结算费率失败', FAILED_CODE);
        }

        // 乐观锁版本号+1
        $updateVersion = $mchAccount['updateVersion'] + 1;

        // 交易可提现 结算金额 余额前后
        $settleAmount = $tradeOrder['settleAmount'];
        $beforeSettleAmountTradeCashAmount = $mchAccount['tradeCashAmount'];
        $afterSettleAmountTradeCashAmount = $mchAccount['tradeCashAmount'] + $settleAmount;

        // 交易可提现 交易手续费 余额前后
        $serviceFee = $this->CountAmountService->countCommonFee($settleAmount, $rateSettle['serviceFee']);
        $beforeServiceFeeTradeCashAmount = $afterSettleAmountTradeCashAmount;
        $afterServiceFeeTradeCashAmount = $beforeServiceFeeTradeCashAmount - $serviceFee;

        // 交易可提现 单笔手续费 余额前后
        $perFee = $rateSettle['perFee'];
        $beforePerFeeTradeCashAmount = $afterServiceFeeTradeCashAmount;
        $afterPerFeeTradeCashAmount = $beforePerFeeTradeCashAmount - $perFee;

        // 交易可提现 保证金 余额前后
        $bondAmount = $this->CountAmountService->countCommonFee($settleAmount, $rateSettle['bondFee']);
        $beforeBondAmountTradeCashAmount = $afterPerFeeTradeCashAmount;
        $afterBondAmountTradeCashAmount = $beforeBondAmountTradeCashAmount - $bondAmount;

        // 保证金账户 保证金 余额前后
        $beforeInBondAmount = $mchAccount['totalBondAmount'];
        $afterInBondAmount = $beforeInBondAmount + $bondAmount;

        // 最后算总的
        $tradeCashAmount = $mchAccount['tradeCashAmount'] + $settleAmount - $serviceFee - $perFee - $bondAmount;
        $totalTradeAmount = $mchAccount['totalTradeAmount'] + $settleAmount;
        $totalBondAmount = $mchAccount['totalBondAmount'] + $bondAmount;
        $bondFrozenAmount = $mchAccount['bondFrozenAmount'] + $bondAmount;

        // 开启事务
        Db::beginTransaction();
        try {
            // step
            // 1.结算金额入账可提现账户，总交易账户账户
            // 2.交易手续费出账
            // 3.单笔手续费出账
            // 4.保证金出账可提现账户
            // 5.入账保证金账户
            // 6.如果是3d，产生两个费用，3d判定费，3d处理费
            // 7.更新订单状态，这里如果是强制成功的结算单，需要更新状态
            // 8.更新账户余额

            // step 1
            $this->handleInSettleAmount($param, $tradeOrder, $mchAccount, $settleAmount, $beforeSettleAmountTradeCashAmount, $afterSettleAmountTradeCashAmount);

            // step 2
            $this->handleOutServiceFee($param, $tradeOrder, $mchAccount, $serviceFee, $beforeServiceFeeTradeCashAmount, $afterServiceFeeTradeCashAmount);

            // step 3
            $this->handleOutPerFee($param, $tradeOrder, $mchAccount, $perFee, $beforePerFeeTradeCashAmount, $afterPerFeeTradeCashAmount);

            // step 4
            $this->handleOutBondAmount($param, $tradeOrder, $mchAccount, $bondAmount, $beforeBondAmountTradeCashAmount, $afterBondAmountTradeCashAmount);

            // step 5
            $this->handleInBondAmount($param, $tradeOrder, $mchAccount, $bondAmount, $beforeInBondAmount, $afterInBondAmount);

            // step 6
            $threeDJudgeFee = $rateSettle['threeDJudgeFee'];
            $threeDFee = $rateSettle['threeDFee'];
            if ($tradeOrder['isThreeD'] == 1) {
                $beforeThreeDJudgeFeeTradeCashAmount = $tradeCashAmount;
                $afterThreeDJudgeFeeTradeCashAmount = $tradeCashAmount;
                if ($threeDJudgeFee > 0) {
                    $afterThreeDJudgeFeeTradeCashAmount = $tradeCashAmount - $threeDJudgeFee;
                    $this->handleThreeDJudgeFee($param, $tradeOrder, $mchAccount, $threeDJudgeFee, $beforeThreeDJudgeFeeTradeCashAmount, $afterThreeDJudgeFeeTradeCashAmount);
                }

                $beforeThreeDFeeTradeCashAmount = $afterThreeDJudgeFeeTradeCashAmount;
                $afterThreeDFeeTradeCashAmount = $beforeThreeDFeeTradeCashAmount;
                if ($threeDFee > 0) {
                    $afterThreeDFeeTradeCashAmount = $beforeThreeDFeeTradeCashAmount - $threeDFee;
                    $this->handleThreeDFee($param, $tradeOrder, $mchAccount, $threeDFee, $beforeThreeDFeeTradeCashAmount, $afterThreeDFeeTradeCashAmount);
                }
                // 重新给交易可提现赋一次值
                $tradeCashAmount = $afterThreeDFeeTradeCashAmount;
            }

            // step 7
            $updateTradeOrder = array(
                'isSettle'          => 2,
                'serviceFee'        => $serviceFee,
                'perFee'            => $perFee,
                'bondAmount'        => $bondAmount,
                'settleTime'        => time()
            );
            if ($tradeOrder['isThreeD'] == 1) {
                $updateTradeOrder['threeDJudgeFee'] = $threeDJudgeFee;
                $updateTradeOrder['threeDFee'] = $threeDFee;
            }
            $this->TradeOrderDetailDao->update($param['orderId'], $updateTradeOrder);

            // step 8
            $updateMchAccount = array(
                "totalTradeAmount"  => $totalTradeAmount,
                "tradeCashAmount"   => $tradeCashAmount,
                "totalBondAmount"   => $totalBondAmount,
                "bondFrozenAmount"  => $bondFrozenAmount,
                "updateVersion"     => $updateVersion
            );
            $result = $this->MchAccountDao->updateWhere([
                "id" => $param['mchAccountId'],
                "updateVersion" => $mchAccount['updateVersion']
            ], $updateMchAccount);

            // 如果更新账户失败，重试，最多3次
            if (!$result) {
                throw new \Exception("更新账户失败");
            }

        } catch (\Throwable $e) {
            CustomUtils::xzxDebug($e->getMessage());
            Db::rollBack();

            // 失败重试，最多3次
            $this->tryOneMore($param);

            return CustomUtils::xeServiceReturnData(FAILED_CODE, "交易订单结算失败");
        }
        Db::commit();

        // t + 0 的保证金解冻
        $this->t0bondAmountThaw($param, $rateSettle);

        // 计算订单佣金
        $this->countSalesCommission($tradeOrder, $rateSettle);

        return CustomUtils::xeServiceReturnData(SUCCESS_CODE, "交易订单结算成功");
    }

    /**
     * @param $param
     * @param $tradeOrder
     * @param $mchAccount
     * @param $amount
     * @param $beforeAmount
     * @param $afterAmount
     * 结算金额入账
     */
    private function handleInSettleAmount($param, $tradeOrder, $mchAccount, $amount, $beforeAmount, $afterAmount) {

        // 写主表
        $mchAccountAccess = array(
            "id"           => CustomUtils::createUUID(),
            "mchId"        => $tradeOrder["mchId"],
            "mchNo"        => $tradeOrder["mchNo"],
            "mchAccountId" => $param['mchAccountId'],
            "accessType"   => ACCESS_TYPE_TRADE_ORDER,
            "accountType"  => ACCOUNT_TYPE_CASH,
            "orderId"      => $tradeOrder['id'],
            "tradeNo"      => $tradeOrder['tradeNo'],
            "amount"       => $amount,
            "currency"     => $tradeOrder['settleCurrency'],
            "status"       => 1,
            "remark"       => "交易订单结算入账",
            "createTime"   => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDao->add($mchAccountAccess);

        // 写明细表
        $mchAccountAccessDetail = array(
            "id"                => CustomUtils::createUUID(),
            "mchId"             => $tradeOrder["mchId"],
            "mchNo"             => $tradeOrder["mchNo"],
            "mchAccountId"      => $param['mchAccountId'],
            "accessId"          => $mchAccountAccess['id'],
            "accountType"       => ACCOUNT_TYPE_CASH,
            "inOutType"         => DETAIL_TYPE_IN,
            "type"              => TYPE_TRADE_ORDER_CASH_IN,
            "beforeTotalAmount" => $beforeAmount,
            "afterTotalAmount"  => $afterAmount,
            "amount"            => $amount,
            "orderId"           => $tradeOrder['id'],
            "tradeNo"           => $tradeOrder['tradeNo'],
            "currency"          => $tradeOrder['settleCurrency'],
            "remark"            => "交易订单结算入账",
            "createTime"        => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDetailDao->add($mchAccountAccessDetail);
    }

    /**
     * @param $param
     * @param $tradeOrder
     * @param $mchAccount
     * @param $amount
     * @param $beforeAmount
     * @param $afterAmount
     * 交易手续费
     */
    public function handleOutServiceFee($param, $tradeOrder, $mchAccount, $amount, $beforeAmount, $afterAmount) {
        // 写主表
        $mchAccountAccess = array(
            "id"           => CustomUtils::createUUID(),
            "mchId"        => $tradeOrder["mchId"],
            "mchNo"        => $tradeOrder["mchNo"],
            "mchAccountId" => $param['mchAccountId'],
            "accessType"   => ACCESS_TYPE_TRADE_ORDER,
            "accountType"  => ACCOUNT_TYPE_CASH,
            "orderId"      => $tradeOrder['id'],
            "tradeNo"      => $tradeOrder['tradeNo'],
            "amount"       => -$amount,
            "currency"     => $tradeOrder['settleCurrency'],
            "status"       => 1,
            "remark"       => "交易订单结算交易手续费出账",
            "createTime"   => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDao->add($mchAccountAccess);

        // 写明细表
        $mchAccountAccessDetail = array(
            "id"                => CustomUtils::createUUID(),
            "mchId"             => $tradeOrder["mchId"],
            "mchNo"             => $tradeOrder["mchNo"],
            "mchAccountId"      => $param['mchAccountId'],
            "accessId"          => $mchAccountAccess['id'],
            "accountType"       => ACCOUNT_TYPE_CASH,
            "inOutType"         => DETAIL_TYPE_OUT,
            "type"              => TYPE_TRADE_ORDER_CASH_SERVICE_FEE_OUT,
            "beforeTotalAmount" => $beforeAmount,
            "afterTotalAmount"  => $afterAmount,
            "amount"            => -$amount,
            "currency"          => $tradeOrder['settleCurrency'],
            "orderId"           => $tradeOrder['id'],
            "tradeNo"           => $tradeOrder['tradeNo'],
            "remark"            => "交易订单结算交易手续费出账",
            "createTime"        => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDetailDao->add($mchAccountAccessDetail);
    }

    /**
     * @param $param
     * @param $tradeOrder
     * @param $mchAccount
     * @param $amount
     * @param $beforeAmount
     * @param $afterAmount
     * 单笔手续费
     */
    public function handleOutPerFee($param, $tradeOrder, $mchAccount, $amount, $beforeAmount, $afterAmount) {
        // 写主表
        $mchAccountAccess = array(
            "id"           => CustomUtils::createUUID(),
            "mchId"        => $tradeOrder["mchId"],
            "mchNo"        => $tradeOrder["mchNo"],
            "mchAccountId" => $param['mchAccountId'],
            "accessType"   => ACCESS_TYPE_TRADE_ORDER,
            "accountType"  => ACCOUNT_TYPE_CASH,
            "orderId"      => $tradeOrder['id'],
            "tradeNo"      => $tradeOrder['tradeNo'],
            "amount"       => -$amount,
            "currency"     => $tradeOrder['settleCurrency'],
            "status"       => 1,
            "remark"       => "交易订单结算单笔手续费出账",
            "createTime"   => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDao->add($mchAccountAccess);

        // 写明细表
        $mchAccountAccessDetail = array(
            "id"                => CustomUtils::createUUID(),
            "mchId"             => $tradeOrder["mchId"],
            "mchNo"             => $tradeOrder["mchNo"],
            "mchAccountId"      => $param['mchAccountId'],
            "accessId"          => $mchAccountAccess['id'],
            "accountType"       => ACCOUNT_TYPE_CASH,
            "inOutType"         => DETAIL_TYPE_OUT,
            "type"              => TYPE_TRADE_ORDER_CASH_PER_FEE_OUT,
            "beforeTotalAmount" => $beforeAmount,
            "afterTotalAmount"  => $afterAmount,
            "amount"            => -$amount,
            "currency"          => $tradeOrder['settleCurrency'],
            "orderId"           => $tradeOrder['id'],
            "tradeNo"           => $tradeOrder['tradeNo'],
            "remark"            => "交易订单结算单笔手续费出账",
            "createTime"        => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDetailDao->add($mchAccountAccessDetail);
    }

    /**
     * @param $param
     * @param $tradeOrder
     * @param $mchAccount
     * @param $amount
     * @param $beforeAmount
     * @param $afterAmount
     * 3d判定费用
     */
    public function handleThreeDJudgeFee($param, $tradeOrder, $mchAccount, $amount, $beforeAmount, $afterAmount) {
        // 写主表
        $mchAccountAccess = array(
            "id"           => CustomUtils::createUUID(),
            "mchId"        => $tradeOrder["mchId"],
            "mchNo"        => $tradeOrder["mchNo"],
            "mchAccountId" => $param['mchAccountId'],
            "accessType"   => ACCESS_TYPE_TRADE_ORDER,
            "accountType"  => ACCOUNT_TYPE_CASH,
            "orderId"      => $tradeOrder['id'],
            "tradeNo"      => $tradeOrder['tradeNo'],
            "amount"       => -$amount,
            "currency"     => $tradeOrder['settleCurrency'],
            "status"       => 1,
            "remark"       => "交易订单结算3d判定费用出账",
            "createTime"   => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDao->add($mchAccountAccess);

        // 写明细表
        $mchAccountAccessDetail = array(
            "id"                => CustomUtils::createUUID(),
            "mchId"             => $tradeOrder["mchId"],
            "mchNo"             => $tradeOrder["mchNo"],
            "mchAccountId"      => $param['mchAccountId'],
            "accessId"          => $mchAccountAccess['id'],
            "accountType"       => ACCOUNT_TYPE_CASH,
            "inOutType"         => DETAIL_TYPE_OUT,
            "type"              => TYPE_TRADE_ORDER_CASH_THREE_D_JUDGE_FEE_OUT,
            "beforeTotalAmount" => $beforeAmount,
            "afterTotalAmount"  => $afterAmount,
            "amount"            => -$amount,
            "currency"          => $tradeOrder['settleCurrency'],
            "orderId"           => $tradeOrder['id'],
            "tradeNo"           => $tradeOrder['tradeNo'],
            "remark"            => "交易订单结算3d判定费用出账",
            "createTime"        => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDetailDao->add($mchAccountAccessDetail);
    }

    /**
     * @param $param
     * @param $tradeOrder
     * @param $mchAccount
     * @param $amount
     * @param $beforeAmount
     * @param $afterAmount
     * 3d处理费用
     */
    public function handleThreeDFee($param, $tradeOrder, $mchAccount, $amount, $beforeAmount, $afterAmount) {
        // 写主表
        $mchAccountAccess = array(
            "id"           => CustomUtils::createUUID(),
            "mchId"        => $tradeOrder["mchId"],
            "mchNo"        => $tradeOrder["mchNo"],
            "mchAccountId" => $param['mchAccountId'],
            "accessType"   => ACCESS_TYPE_TRADE_ORDER,
            "accountType"  => ACCOUNT_TYPE_CASH,
            "orderId"      => $tradeOrder['id'],
            "tradeNo"      => $tradeOrder['tradeNo'],
            "amount"       => -$amount,
            "currency"     => $tradeOrder['settleCurrency'],
            "status"       => 1,
            "remark"       => "交易订单结算3d处理费用出账",
            "createTime"   => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDao->add($mchAccountAccess);

        // 写明细表
        $mchAccountAccessDetail = array(
            "id"                => CustomUtils::createUUID(),
            "mchId"             => $tradeOrder["mchId"],
            "mchNo"             => $tradeOrder["mchNo"],
            "mchAccountId"      => $param['mchAccountId'],
            "accessId"          => $mchAccountAccess['id'],
            "accountType"       => ACCOUNT_TYPE_CASH,
            "inOutType"         => DETAIL_TYPE_OUT,
            "type"              => TYPE_TRADE_ORDER_CASH_THREE_D_FEE_FEE_OUT,
            "beforeTotalAmount" => $beforeAmount,
            "afterTotalAmount"  => $afterAmount,
            "amount"            => -$amount,
            "currency"          => $tradeOrder['settleCurrency'],
            "orderId"           => $tradeOrder['id'],
            "tradeNo"           => $tradeOrder['tradeNo'],
            "remark"            => "交易订单结算3d处理费用出账",
            "createTime"        => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDetailDao->add($mchAccountAccessDetail);
    }

    /**
     * @param $param
     * @param $tradeOrder
     * @param $mchAccount
     * @param $amount
     * @param $beforeAmount
     * @param $afterAmount
     * 保证金出账
     */
    public function handleOutBondAmount($param, $tradeOrder, $mchAccount, $amount, $beforeAmount, $afterAmount) {
        // 写主表
        $mchAccountAccess = array(
            "id"           => CustomUtils::createUUID(),
            "mchId"        => $tradeOrder["mchId"],
            "mchNo"        => $tradeOrder["mchNo"],
            "mchAccountId" => $param['mchAccountId'],
            "accessType"   => ACCESS_TYPE_TRADE_ORDER_THAW_BOND,
            "accountType"  => ACCOUNT_TYPE_CASH,
            "orderId"      => $tradeOrder['id'],
            "tradeNo"      => $tradeOrder['tradeNo'],
            "amount"       => -$amount,
            "currency"     => $tradeOrder['settleCurrency'],
            "status"       => 1,
            "remark"       => "交易订单结算保证金出账",
            "createTime"   => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDao->add($mchAccountAccess);

        // 写明细表
        $mchAccountAccessDetail = array(
            "id"                => CustomUtils::createUUID(),
            "mchId"             => $tradeOrder["mchId"],
            "mchNo"             => $tradeOrder["mchNo"],
            "mchAccountId"      => $param['mchAccountId'],
            "accessId"          => $mchAccountAccess['id'],
            "accountType"       => ACCOUNT_TYPE_CASH,
            "inOutType"         => DETAIL_TYPE_OUT,
            "type"              => TYPE_TRADE_ORDER_CASH_BOND_AMOUNT_OUT,
            "beforeTotalAmount" => $beforeAmount,
            "afterTotalAmount"  => $afterAmount,
            "amount"            => -$amount,
            "currency"          => $tradeOrder['settleCurrency'],
            "orderId"           => $tradeOrder['id'],
            "tradeNo"           => $tradeOrder['tradeNo'],
            "remark"            => "交易订单结算保证金出账",
            "createTime"        => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDetailDao->add($mchAccountAccessDetail);
    }

    /**
     * @param $param
     * @param $tradeOrder
     * @param $mchAccount
     * @param $amount
     * @param $beforeAmount
     * @param $afterAmount
     * 保证金入账
     */
    public function handleInBondAmount($param, $tradeOrder, $mchAccount, $amount, $beforeAmount, $afterAmount) {
        // 写主表
        $mchAccountAccess = array(
            "id"           => CustomUtils::createUUID(),
            "mchId"        => $tradeOrder["mchId"],
            "mchNo"        => $tradeOrder["mchNo"],
            "mchAccountId" => $param['mchAccountId'],
            "accessType"   => ACCESS_TYPE_TRADE_ORDER_THAW_BOND,
            "accountType"  => ACCOUNT_TYPE_BOND_FROZEN,
            "orderId"      => $tradeOrder['id'],
            "tradeNo"      => $tradeOrder['tradeNo'],
            "amount"       => $amount,
            "currency"     => $tradeOrder['settleCurrency'],
            "status"       => 1,
            "remark"       => "交易订单保证金结算入账",
            "createTime"   => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDao->add($mchAccountAccess);

        // 写明细表
        $mchAccountAccessDetail = array(
            "id"                => CustomUtils::createUUID(),
            "mchId"             => $tradeOrder["mchId"],
            "mchNo"             => $tradeOrder["mchNo"],
            "mchAccountId"      => $param['mchAccountId'],
            "accessId"          => $mchAccountAccess['id'],
            "accountType"       => ACCOUNT_TYPE_BOND_FROZEN,
            "inOutType"         => DETAIL_TYPE_IN,
            "type"              => TYPE_TRADE_ORDER_BOND_FROZEN_CYCLE_IN,
            "beforeTotalAmount" => $beforeAmount,
            "afterTotalAmount"  => $afterAmount,
            "amount"            => $amount,
            "currency"          => $tradeOrder['settleCurrency'],
            "orderId"           => $tradeOrder['id'],
            "tradeNo"           => $tradeOrder['tradeNo'],
            "remark"            => "交易订单保证金结算入账",
            "createTime"        => CustomUtils::xzxGetMsecTime()
        );
        $this->MchAccountAccessDetailDao->add($mchAccountAccessDetail);
    }

    /**
     * @param $param
     * @param $rateSettle
     * t+0保证金解冻
     */
    private function t0bondAmountThaw($param, $rateSettle) {
        // 如果保证金解冻周期是0，则创建一条消息，进行马上解冻
        if ($rateSettle['bondWithdrawPeriod'] == 0) {
            $this->addMq([
                'accessType'   => ACCESS_TYPE_BOND_THAW,
                'orderId'      => $param['orderId'],
                'mchAccountId' => $param['mchAccountId'],
            ]);
        }
    }

    /**
     * @param $tradeOrder
     * @param $rateSettle
     * 计算这个订单的佣金
     * 公式： （商户交易手续费率 - 通道交易手续费率） * 商户结算金额 * 佣金比例
     * 销售一级，销售二级
     */
    public function countSalesCommission($tradeOrder, $rateSettle) {
        $mch = $this->MchInfoDao->get($tradeOrder['mchId']);
        // 没有关联销售
        if (empty($mch['salesId'])) {
            CustomUtils::xzxDebug("{$tradeOrder['mchNo']} 未关联销售");
            return;
        }

        // 查关联销售信息
        $sales = $this->SysAdminDao->get($mch['salesId']);
        if (empty($sales) || empty($sales['parentId'])) {
            CustomUtils::xzxDebug("{$tradeOrder['mchNo']} 关联销售找不到或未设置上级");
            return;
        }

        // 查销售佣金比例
        $rateCommission2 = $this->RateCommissionSalesDao->getWhere(['level' => 2]);
        $rateCommission1 = $this->RateCommissionSalesDao->getWhere(['level' => 1]);

        if (empty($rateCommission2) || empty($rateCommission1)) {
            CustomUtils::xzxDebug("未设置好一二级销售佣金比例");
            return;
        }

        // 查通道的成本
        $rateCost = $this->RateCostDao->getByChannelId($tradeOrder['channelId']);
        if (empty($rateCost)) {
            CustomUtils::xzxDebug("{$tradeOrder['channelName']} 未设置关联成本");
            return;
        }
        if ($rateCost['serviceFee'] >= $rateSettle['serviceFee']) {
            CustomUtils::xzxDebug("成本交易手续费率大于商户交易手续费率，无法计算佣金");
            return;
        }

        // 计算一级二级佣金
        bcscale(8);
        $settleAmount = strval($tradeOrder['settleAmount']);
        $differ = bcdiv(strval($rateSettle['serviceFee'] - $rateCost['serviceFee']), '10000');
        $rate2 = bcdiv(strval($rateCommission2['rate']), '10000');
        $salesCommission2 = round(bcmul(bcmul($differ, $settleAmount), $rate2));

        $rate1 = bcdiv(strval($rateCommission1['rate']), '10000');
        $salesCommission1 = round(bcmul(bcmul($differ, $settleAmount), $rate1));

        // 更新订单佣金信息
        $this->TradeOrderDetailDao->update($tradeOrder['id'], [
            'salesId1'          => $sales['parentId'],
            'salesId2'          => $sales['id'],
            'salesCommission1'  => $salesCommission1,
            'salesCommission2'  => $salesCommission2,
        ]);
    }

}